EDA Report
The goal of this section is to understand the overall shape of our
data.
Basic Plots
# Inspections by City
ggplot(inspections, aes(x = city_source)) + geom_bar() + labs(title = "Inspections by City") + theme_minimal()

#Outcomes
ggplot(inspections, aes(x = inspection_outcome)) +
geom_bar() +
scale_y_continuous(labels = label_comma()) +
labs(title = "Outcomes")

#Risks
ggplot(inspections, aes(x = risk_level_standard)) +
labs(title = "Risks") +
scale_y_continuous(labels = label_comma()) +
geom_bar()

#Time Range of the Data
ggplot(inspections, aes(x = inspection_date)) + geom_histogram(bins = 50) +
scale_y_continuous(labels = label_comma()) +
labs(title = "Distribution of Inspections Over Time", x = "Date", y = "Count")

Our initial phase of exploratory data analysis (EDA) focused on
understanding the overall shape, distribution, and integrity of our
combined 1.4 million-row dataset. This initial analysis confirms our
combined dataset is large, usable, and modern, but critically
imbalanced.
Plot 1: Inspections by City This bar chart shows the total number of
inspections contributed by each city. The key finding here is that our
dataset is heavily imbalanced. Boston is the source of a large majority
of our data (over 750,000 rows), while Chicago and New York are
similarly sized, and San Francisco is our smallest dataset.
This is a critical finding because it confirms that we cannot use raw
counts to compare cities. All future city-to-city comparisons must be
based on proportions or percentages (using position = “fill”) to be fair
and accurate.
Plot 2: Overall Inspection Outcomes This plot shows the distribution
of our newly-created inspection_outcome column across the entire
dataset. While “Fail” and “Pass” are the most frequent outcomes, this
plot is heavily skewed by the disproportionate size of the Boston data.
We can’t draw any real conclusions from this yet. Its main purpose for
now is to confirm that our case_when() logic successfully categorized
all 1.4 million rows.
Plot 3: Distribution of Inspections Over Time This histogram is one
of our most important initial plots. It confirms two things:
The data is recent: The vast majority of our inspections occurred
from roughly 2005 to the present, which is excellent for answering our
research questions about modern trends.
We have “bad data” to filter: The plot clearly identifies a small
cluster of “bad data” (placeholder dates from 1900) that we must filter
out before conducting any time-series analysis. The warning message also
confirmed that a negligible number of rows (~6,400, or <0.5%) were
dropped due to missing dates, which will not impact our analysis.
City Comparisons
#Outcomes by City
ggplot(inspections, aes(x = city_source, fill = inspection_outcome)) +
geom_bar(position = "fill") +
labs(title = "Outcomes by City", y = "Proportion")

#Risk Level by City
ggplot(inspections, aes(x = city_source, fill = risk_level_standard)) +
geom_bar(position = "fill") +
labs(title = "Risk Level by City", y = "Proportion")

#Score Distributions
ggplot(inspections, aes(x = city_source, y = inspection_score)) +
geom_boxplot() +
labs(title = "Score Distributions")

ggplot(inspections, aes(x = inspection_outcome, y = inspection_score, fill = city_source)) +
geom_boxplot() +
facet_wrap(~ city_source) + #show how our standardized Pass/Fail categories line up with the numeric scores
labs(title = "Score Distributions by City (Standardized")

After establishing the overall shape of our data, we drilled down to
compare the four cities. This is where our standardization efforts
provide their first major insights, revealing that the cities have
vastly different inspection profiles.
Plot 4: Proportions of Outcomes by City This plot directly compares
the pass/fail rates for each city. We found that Boston and San
Francisco have the highest proportion of “Fail” outcomes. In contrast,
New York’s profile is dominated by “Pass” (reflecting their ‘A’ grades)
and “Pending” results. This confirms that each city’s grading system is
unique and that our inspection_outcome column successfully captured
these differences.
Plot 5: Proportion of Risk Level by City This is one of the most
striking findings so far. Chicago and New York log a dramatically higher
proportion of “High Risk” violations than Boston and San Francisco. In
Chicago, “High Risk” appears to be the most common category, while in
Boston, “Low Risk” is dominant. This may reflect different public health
definitions of “risk” or different areas of focus for each city’s
inspectors.
Plot 6 & 7: Score Distributions These two plots (which we’ve
combined for analysis) confirm our inspection_outcome logic and reveal
the inverted nature of the scoring systems.
NYC uses a demerit system: A lower score is better. Our plot shows
that “Pass” (Grade A) has the lowest scores, while “Fail” (Grade C) has
the highest.
SF uses a points-based system: A higher score is better. Our plot
confirms this, showing “Pass” (90+) has the highest scores and “Fail”
(71-85) has lower scores.
This analysis validates our standardization and proves that the two
scoring systems are direct opposites.
Exploring Fail Rates Over Time
# Create a summary table
fails_by_year <- inspections |>
filter(inspection_date > "2000-01-01") |> # filter out 'bad' dates
mutate(year = year(inspection_date)) |>
group_by(city_source, year) |>
summarize(
fail_rate = mean(inspection_outcome == "Fail", na.rm = TRUE),
total_inspections = n()
) |>
filter(total_inspections > 100) # Remove years with tiny data
# Plot the summary
ggplot(fails_by_year, aes(x = year, y = fail_rate, color = city_source)) +
geom_line(linewidth = 1) +
geom_point(size = 2) +
scale_y_continuous(labels = label_percent()) + # format y-axis as percentage
scale_color_viridis_d() + # add better colors
labs(
title = "Fail Rate Over Time by City",
y = "Proportion of Fails", # <-- Fix y-axis label
x = "Year",
color = "City" # <-- Fix legend title
)

# Least Successful zipcodes in each city in the dataset
fails_by_zip <- inspections |>
filter(inspection_date > "2000-01-01") |> # Good idea to filter bad dates
group_by(city_source, zip_code) |>
summarize(
fail_rate = mean(inspection_outcome == "Fail", na.rm = TRUE),
total_inspections = n()
) |>
filter(total_inspections > 100) |> # Only include zips with 100+ inspections
ungroup()
# Summary table for zip codes
fails_by_zip |>
group_by(city_source) |> # Group by city
top_n(3, fail_rate) |> # Find the top 3 *within* that city
ungroup() |>
# This 'reorder_within' is a special trick to make facets work
mutate(
zip_code = tidytext::reorder_within(zip_code, fail_rate, city_source)
) |>
ggplot(aes(x = zip_code, y = fail_rate, fill = city_source)) +
geom_col() +
tidytext::scale_x_reordered() + # This makes the labels plot correctly
facet_wrap(~ city_source, scales = "free") + #Create 4 separate charts
coord_flip() +
labs(
title = "Top 3 Zip Codes with Highest Fail Rate by City",
x = "Zip Code",
y = "Fail Rate"
) +
theme(legend.position = "none")

Following our city-level comparisons, we moved into our first
multivariate analysis to answer our research questions about where and
when violations occur.
Plot 8: Fail Rate Over Time by City This line graph plots the
proportion (percentage) of “Fail” outcomes for each city, from 2008 to
2025. This is our most significant finding so far:
Dramatically Different Systems: The definition of a “Fail” is clearly
not standardized.
Boston: Has a very high and consistent “Fail” rate, hovering around
60% for the entire 15-year period. This strongly suggests that Boston’s
result column logs a “Fail” for even minor infractions, making it a very
common outcome.
Chicago: Shows a positive trend. Its fail rate has steadily decreased
from ~25% in 2010 to a stable ~18-20% in recent years.
New York: Has an extremely low fail rate, consistently staying below
10%. This aligns perfectly with their “Grade A” system, where a ‘C’
(which we mapped to “Fail”) is rare.
San Francisco: Appears to have a fail rate of around 30%, landing
between Boston and the other two cities.
Plot 9: Top 3 Worst Zip Codes by City This bar chart was intended to
find the “worst” zip codes across the entire dataset. We have now
successfully identified specific geographic areas of concern for each
city:
Boston: 02119-3212, 02120
Chicago: 60827, 60619
New York: 11436, 11428
San Francisco: 94134, 94118
Boston Zipcodes Map
There are 43 zip codes in the City of Boston
Top Violations Overall
top_bigrams <- inspections |>
sample_frac(0.5) |> # Taking a 50% random sample to reduce memory load
filter(!is.na(violation_desc)) |>
unnest_tokens(bigram, violation_desc, token = "ngrams", n = 2) |>
count(bigram, sort = TRUE)
# Plot the top 20
top_bigrams |>
top_n(20) |>
ggplot(aes(x = reorder(bigram, n), y = n)) +
geom_col() +
coord_flip() +
labs(
title = "Top 20 Most Common Violation Phrases (50% Sample)",
x = "Violation Phrase (Bigram)",
y = "Total Count"
)

This plot, despite successfully processing the text, shows that the
most common phrases across all cities are generic, high-frequency
functional words like ‘food contact’ and ‘non food’. We do not see
specific issues like ‘rodent’ or ‘improper temperature’ in the top 20,
confirming that these key issues are diluted by common, general phrases.
This validates our next step to use manual keyword searching to group
thousands of unique violations into meaningful categories.
Days of the week that see the most inspections
inspections |>
mutate(wday = wday(inspection_date, label = TRUE)) |>
count(wday) |>
ggplot(aes(wday, n)) +
geom_col() +
scale_y_continuous(labels = label_comma()) +
labs(title = "Inspections by Day of Week")

This analysis confirms that inspection frequency is heavily skewed
toward weekdays, with a slight peak on Tuesday. The low counts on Sunday
and Saturday suggest that weekend inspections are rare or reserved only
for specific facilities.
Inspection Frequency per Restaurant
ggplot(inspections |> count(restaurant_name), aes(n)) +
geom_histogram(breaks = seq(0, 50, by = 1), color="black", fill="skyblue") +
labs(title="Distribution of Inspections per Restaurant", x="Number of Inspections", y="Number of Restaurants")

The tallest bar shows that nearly 10,000 restaurants have been
inspected only once (or close to once) during the dataset’s time frame.
The number of restaurants drops off steeply for businesses inspected
just 2, 3, or 4 times. The long, flat tail on the right is highly
significant. While most businesses are inspected infrequently, a small
but consistent number of restaurants are inspected 20, 30, 40, or even
50+ times. This may be due to routine inspections happening, but this is
unlikely for the time period covered in our data. This coudl also
suggest that the inspection system is effectively using a risk-based
approach. Restaurants that fail or have serious violations are likely
pushed into re-inspection cycles or receive more frequent routine
inspections. Conversely, successful restaurants are inspected less
often, freeing up resources.
Seun’s Analysis
Categorize Violations
inspections_categorized <- inspections |>
mutate(
violation_category = case_when(
str_detect(violation_desc, "mice|rodent|droppings|insects|pests|harborage") ~ "Pest Control",
str_detect(violation_desc, "temperature|cool|hot-holding|cold-holding|refrigerat") ~ "Food Temperature",
str_detect(violation_desc, "wash|sanitiz|clean|wiping cloths|dishwashing") ~ "Sanitation & Cleaning",
str_detect(violation_desc, "hand wash|hygiene|no hair|bare hand") ~ "Employee Hygiene",
str_detect(violation_desc, "contaminat|cross-contamination|raw|covered|protect") ~ "Cross-Contamination",
str_detect(violation_desc, "floor|wall|ceiling|plumbing|ventilation|garbage") ~ "Facility/Maintenance",
TRUE ~ "Other"
)
)
#Check new categories
inspections_categorized |>
count(violation_category, sort = TRUE)
Categorize Restaurants
inspections_categorized <- inspections_categorized |>
mutate(
# Create one combined description column to search
desc_all = coalesce(cuisine_description, facility_type, descript) |> tolower(),
restaurant_category = case_when(
str_detect(desc_all, "pizza|pizzeria") ~ "Pizza",
str_detect(desc_all, "sushi|japanese") ~ "Sushi/Japanese",
str_detect(desc_all, "coffee|cafe|bakery|donut") ~ "Coffee/Bakery",
str_detect(desc_all, "mexican|taco") ~ "Mexican",
str_detect(desc_all, "chinese") ~ "Chinese",
str_detect(desc_all, "sandwich|deli|sub") ~ "Sandwich/Deli",
str_detect(desc_all, "bar|tavern|pub") ~ "Bar/Pub",
str_detect(desc_all, "restaurant|american") ~ "Restaurant (General)",
str_detect(desc_all, "school|grocery|market|caterer|kitchen") ~ "Other (Grocery/School/Etc.)",
TRUE ~ "Other"
)
)
#Check new categories
inspections_categorized |>
count(restaurant_category, sort = TRUE)
Violation “Fingerprint” Plot
#Summary table
violation_fingerprint <- inspections_categorized |>
filter(
restaurant_category != "Other",
restaurant_category != "Other (Grocery/School/Etc.)",
violation_category != "Other"
) |>
count(restaurant_category, violation_category) |>
group_by(restaurant_category) |>
mutate(proportion = n / sum(n)) |>
ungroup()
# Plot the "fingerprint"
ggplot(violation_fingerprint,
aes(x = violation_category, y = proportion, fill = violation_category)) +
geom_col() +
facet_wrap(~ restaurant_category) +
scale_y_continuous(labels = label_percent()) +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
legend.position = "bottom"
) +
labs(
title = "Violation 'Fingerprint' by Restaurant Category",
y = "Proportion of All Violations",
x = "Violation Type",
fill = "Violation Category"
)

Restaurant categories do disproportionately receive certain violation
types. While “Sanitation & Cleaning” is a universal problem,
specific models carry unique risks. The most important takeaway is that
Sanitation & Cleaning (pink) and Pest Control (blue) are the two
largest violation categories across nearly all restaurant types.
However, the proportion of other key categories reveals important
differences:
Pest Control Dominance:
Sushi/Japanese, Sandwich/Deli, and Bar/Pubs have the highest
proportion of Pest Control violations, consistently making up over 25%
of their total issues.
Sanitation & Cleaning Focus:
Coffee/Bakery, Pizza, and Chinese restaurants are highly dominated by
Sanitation & Cleaning violations (pink), with this category often
exceeding 40% of their total violations.
Food Temperature Risk (The Outlier):
Restaurant (General) is the only category where Food Temperature
(teal) makes up the largest non-Sanitation/Pest share, hitting
approximately 25–30% of its violations. This suggests that businesses
with diverse menus and complex cooking processes are uniquely prone to
temperature-related failures.
Cross-Contamination Risk:
Mexican and Sandwich/Deli restaurants show a slightly elevated
proportional risk for Cross-Contamination (red), often related to the
high volume of raw preparation (e.g., cutting vegetables, preparing
salsas, handling deli meats).
Standardize Inspection Types
inspections_categorized <- inspections_categorized |>
mutate(
type_lower = tolower(inspection_type),
inspection_type_standard = case_when(
# Keywords for complaint
str_detect(type_lower, "complaint|311|owner complaint") ~ "Complaint",
# Keywords for routine
str_detect(type_lower, "routine|cycle|canvass|regular") ~ "Routine",
# Keywords for follow-ups
str_detect(type_lower, "re-inspection|reinspection|follow-up") ~ "Follow-Up",
TRUE ~ "Other"
)
)
#new standardized categories
inspections_categorized |>
count(inspection_type_standard, sort = TRUE)
Plot Severity by Inspection Type
inspections_categorized |>
# 1. Filter the data (No changes needed here)
filter(
inspection_type_standard %in% c("Routine", "Complaint"),
risk_level_standard != "Unknown"
) |> # <--- PIPE TO THE NEXT STEP
# 2. Mutate (Convert to Factor)
mutate(
risk_level_standard = factor(
risk_level_standard,
# Set the desired hierarchical order
levels = c("High", "Medium", "Low"),
ordered = TRUE
)
) |> # <--- CORRECT PIPE PLACEMENT (Outside the final mutate parenthesis)
# 3. Plot proportions
ggplot(aes(x = inspection_type_standard, fill = risk_level_standard)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::label_percent()) +
scale_fill_viridis_d(option = "C") +
labs(
title = "Violation Severity by Inspection Type",
x = "Inspection Type",
y = "Proportion of Violations",
fill = "Risk Level"
)

The proportional plot clearly shows that Complaint-Driven inspections
are more likely to find severe problems than Routine inspections12. The
proportion of High Risk violations is visually larger in the Complaint
column than in the Routine column13. This suggests the public is
effective at reporting restaurants that pose an immediate public health
risk.
LS0tCnRpdGxlOiAiUiBTdHVkZW50cyBQcm9qZWN0IE5vdGVib29rIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIHBkZl9kb2N1bWVudDogZGVmYXVsdAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgojIyMgTG9hZCBMaWJyYXJpZXMgYW5kIERhdGEKYGBge3Igc2V0dXAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KGx1YnJpZGF0ZSkKbGlicmFyeSh0aWR5dGV4dCkKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkodmlyaWRpcykKCiMgTG9hZCB0aGUgc2luZ2xlLCBmaW5hbCBjbGVhbiBmaWxlCmluc3BlY3Rpb25zIDwtIHJlYWRfY3N2KCJkYXRhL2luc3BlY3Rpb25zX2NsZWFuLmNzdiIpCmBgYAoKIyMgRURBIFJlcG9ydApUaGUgZ29hbCBvZiB0aGlzIHNlY3Rpb24gaXMgdG8gdW5kZXJzdGFuZCB0aGUgb3ZlcmFsbCBzaGFwZSBvZiBvdXIgZGF0YS4KCiMjIyBCYXNpYyBQbG90cwpgYGB7ciBCYXNpYyBQbG90c30KIyBJbnNwZWN0aW9ucyBieSBDaXR5CmdncGxvdChpbnNwZWN0aW9ucywgYWVzKHggPSBjaXR5X3NvdXJjZSkpICsgZ2VvbV9iYXIoKSArIGxhYnModGl0bGUgPSAiSW5zcGVjdGlvbnMgYnkgQ2l0eSIpICsgdGhlbWVfbWluaW1hbCgpCgojT3V0Y29tZXMKZ2dwbG90KGluc3BlY3Rpb25zLCBhZXMoeCA9IGluc3BlY3Rpb25fb3V0Y29tZSkpICsgCiAgZ2VvbV9iYXIoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX2NvbW1hKCkpICsKICBsYWJzKHRpdGxlID0gIk91dGNvbWVzIikKCiNSaXNrcwpnZ3Bsb3QoaW5zcGVjdGlvbnMsIGFlcyh4ID0gcmlza19sZXZlbF9zdGFuZGFyZCkpICsgCiAgbGFicyh0aXRsZSA9ICJSaXNrcyIpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGxhYmVsX2NvbW1hKCkpICsgCiAgZ2VvbV9iYXIoKQogIAojVGltZSBSYW5nZSBvZiB0aGUgRGF0YQpnZ3Bsb3QoaW5zcGVjdGlvbnMsIGFlcyh4ID0gaW5zcGVjdGlvbl9kYXRlKSkgKyBnZW9tX2hpc3RvZ3JhbShiaW5zID0gNTApICsgCnNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9jb21tYSgpKSArCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgSW5zcGVjdGlvbnMgT3ZlciBUaW1lIiwgeCA9ICJEYXRlIiwgeSA9ICJDb3VudCIpCmBgYApPdXIgaW5pdGlhbCBwaGFzZSBvZiBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIChFREEpIGZvY3VzZWQgb24gdW5kZXJzdGFuZGluZyB0aGUgb3ZlcmFsbCBzaGFwZSwgZGlzdHJpYnV0aW9uLCBhbmQgaW50ZWdyaXR5IG9mIG91ciBjb21iaW5lZCAxLjQgbWlsbGlvbi1yb3cgZGF0YXNldC4gVGhpcyBpbml0aWFsIGFuYWx5c2lzIGNvbmZpcm1zIG91ciBjb21iaW5lZCBkYXRhc2V0IGlzIGxhcmdlLCB1c2FibGUsIGFuZCBtb2Rlcm4sIGJ1dCBjcml0aWNhbGx5IGltYmFsYW5jZWQuCgpQbG90IDE6IEluc3BlY3Rpb25zIGJ5IENpdHkKVGhpcyBiYXIgY2hhcnQgc2hvd3MgdGhlIHRvdGFsIG51bWJlciBvZiBpbnNwZWN0aW9ucyBjb250cmlidXRlZCBieSBlYWNoIGNpdHkuIFRoZSBrZXkgZmluZGluZyBoZXJlIGlzIHRoYXQgb3VyIGRhdGFzZXQgaXMgaGVhdmlseSBpbWJhbGFuY2VkLiBCb3N0b24gaXMgdGhlIHNvdXJjZSBvZiBhIGxhcmdlIG1ham9yaXR5IG9mIG91ciBkYXRhIChvdmVyIDc1MCwwMDAgcm93cyksIHdoaWxlIENoaWNhZ28gYW5kIE5ldyBZb3JrIGFyZSBzaW1pbGFybHkgc2l6ZWQsIGFuZCBTYW4gRnJhbmNpc2NvIGlzIG91ciBzbWFsbGVzdCBkYXRhc2V0LgoKVGhpcyBpcyBhIGNyaXRpY2FsIGZpbmRpbmcgYmVjYXVzZSBpdCBjb25maXJtcyB0aGF0IHdlIGNhbm5vdCB1c2UgcmF3IGNvdW50cyB0byBjb21wYXJlIGNpdGllcy4gQWxsIGZ1dHVyZSBjaXR5LXRvLWNpdHkgY29tcGFyaXNvbnMgbXVzdCBiZSBiYXNlZCBvbiBwcm9wb3J0aW9ucyBvciBwZXJjZW50YWdlcyAodXNpbmcgcG9zaXRpb24gPSAiZmlsbCIpIHRvIGJlIGZhaXIgYW5kIGFjY3VyYXRlLgoKUGxvdCAyOiBPdmVyYWxsIEluc3BlY3Rpb24gT3V0Y29tZXMKVGhpcyBwbG90IHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2Ygb3VyIG5ld2x5LWNyZWF0ZWQgaW5zcGVjdGlvbl9vdXRjb21lIGNvbHVtbiBhY3Jvc3MgdGhlIGVudGlyZSBkYXRhc2V0LiBXaGlsZSAiRmFpbCIgYW5kICJQYXNzIiBhcmUgdGhlIG1vc3QgZnJlcXVlbnQgb3V0Y29tZXMsIHRoaXMgcGxvdCBpcyBoZWF2aWx5IHNrZXdlZCBieSB0aGUgZGlzcHJvcG9ydGlvbmF0ZSBzaXplIG9mIHRoZSBCb3N0b24gZGF0YS4gV2UgY2FuJ3QgZHJhdyBhbnkgcmVhbCBjb25jbHVzaW9ucyBmcm9tIHRoaXMgeWV0LiBJdHMgbWFpbiBwdXJwb3NlIGZvciBub3cgaXMgdG8gY29uZmlybSB0aGF0IG91ciBjYXNlX3doZW4oKSBsb2dpYyBzdWNjZXNzZnVsbHkgY2F0ZWdvcml6ZWQgYWxsIDEuNCBtaWxsaW9uIHJvd3MuCgpQbG90IDM6IERpc3RyaWJ1dGlvbiBvZiBJbnNwZWN0aW9ucyBPdmVyIFRpbWUKVGhpcyBoaXN0b2dyYW0gaXMgb25lIG9mIG91ciBtb3N0IGltcG9ydGFudCBpbml0aWFsIHBsb3RzLiBJdCBjb25maXJtcyB0d28gdGhpbmdzOgoKVGhlIGRhdGEgaXMgcmVjZW50OiBUaGUgdmFzdCBtYWpvcml0eSBvZiBvdXIgaW5zcGVjdGlvbnMgb2NjdXJyZWQgZnJvbSByb3VnaGx5IDIwMDUgdG8gdGhlIHByZXNlbnQsIHdoaWNoIGlzIGV4Y2VsbGVudCBmb3IgYW5zd2VyaW5nIG91ciByZXNlYXJjaCBxdWVzdGlvbnMgYWJvdXQgbW9kZXJuIHRyZW5kcy4KCldlIGhhdmUgImJhZCBkYXRhIiB0byBmaWx0ZXI6IFRoZSBwbG90IGNsZWFybHkgaWRlbnRpZmllcyBhIHNtYWxsIGNsdXN0ZXIgb2YgImJhZCBkYXRhIiAocGxhY2Vob2xkZXIgZGF0ZXMgZnJvbSAxOTAwKSB0aGF0IHdlIG11c3QgZmlsdGVyIG91dCBiZWZvcmUgY29uZHVjdGluZyBhbnkgdGltZS1zZXJpZXMgYW5hbHlzaXMuIFRoZSB3YXJuaW5nIG1lc3NhZ2UgYWxzbyBjb25maXJtZWQgdGhhdCBhIG5lZ2xpZ2libGUgbnVtYmVyIG9mIHJvd3MgKH42LDQwMCwgb3IgPDAuNSUpIHdlcmUgZHJvcHBlZCBkdWUgdG8gbWlzc2luZyBkYXRlcywgd2hpY2ggd2lsbCBub3QgaW1wYWN0IG91ciBhbmFseXNpcy4KCgojIyMgQ2l0eSBDb21wYXJpc29ucwpgYGB7ciBDaXR5IENvbXBhcmlzb25zfQojT3V0Y29tZXMgYnkgQ2l0eQpnZ3Bsb3QoaW5zcGVjdGlvbnMsIGFlcyh4ID0gY2l0eV9zb3VyY2UsIGZpbGwgPSBpbnNwZWN0aW9uX291dGNvbWUpKSArIAogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArIAogIGxhYnModGl0bGUgPSAiT3V0Y29tZXMgYnkgQ2l0eSIsIHkgPSAiUHJvcG9ydGlvbiIpCgojUmlzayBMZXZlbCBieSBDaXR5CmdncGxvdChpbnNwZWN0aW9ucywgYWVzKHggPSBjaXR5X3NvdXJjZSwgZmlsbCA9IHJpc2tfbGV2ZWxfc3RhbmRhcmQpKSArIAogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArCiAgICBsYWJzKHRpdGxlID0gIlJpc2sgTGV2ZWwgYnkgQ2l0eSIsIHkgPSAiUHJvcG9ydGlvbiIpCgojU2NvcmUgRGlzdHJpYnV0aW9ucwpnZ3Bsb3QoaW5zcGVjdGlvbnMsIGFlcyh4ID0gY2l0eV9zb3VyY2UsIHkgPSBpbnNwZWN0aW9uX3Njb3JlKSkgKyAKICBnZW9tX2JveHBsb3QoKSArCiAgICBsYWJzKHRpdGxlID0gIlNjb3JlIERpc3RyaWJ1dGlvbnMiKQoKZ2dwbG90KGluc3BlY3Rpb25zLCBhZXMoeCA9IGluc3BlY3Rpb25fb3V0Y29tZSwgeSA9IGluc3BlY3Rpb25fc2NvcmUsIGZpbGwgPSBjaXR5X3NvdXJjZSkpICsKICBnZW9tX2JveHBsb3QoKSArIAogIGZhY2V0X3dyYXAofiBjaXR5X3NvdXJjZSkgKyAjc2hvdyBob3cgb3VyIHN0YW5kYXJkaXplZCBQYXNzL0ZhaWwgY2F0ZWdvcmllcyBsaW5lIHVwIHdpdGggdGhlIG51bWVyaWMgc2NvcmVzCiAgICBsYWJzKHRpdGxlID0gIlNjb3JlIERpc3RyaWJ1dGlvbnMgYnkgQ2l0eSAoU3RhbmRhcmRpemVkIikKCmBgYApBZnRlciBlc3RhYmxpc2hpbmcgdGhlIG92ZXJhbGwgc2hhcGUgb2Ygb3VyIGRhdGEsIHdlIGRyaWxsZWQgZG93biB0byBjb21wYXJlIHRoZSBmb3VyIGNpdGllcy4gVGhpcyBpcyB3aGVyZSBvdXIgc3RhbmRhcmRpemF0aW9uIGVmZm9ydHMgcHJvdmlkZSB0aGVpciBmaXJzdCBtYWpvciBpbnNpZ2h0cywgcmV2ZWFsaW5nIHRoYXQgdGhlIGNpdGllcyBoYXZlIHZhc3RseSBkaWZmZXJlbnQgaW5zcGVjdGlvbiBwcm9maWxlcy4KClBsb3QgNDogUHJvcG9ydGlvbnMgb2YgT3V0Y29tZXMgYnkgQ2l0eSAKVGhpcyBwbG90IGRpcmVjdGx5IGNvbXBhcmVzIHRoZSBwYXNzL2ZhaWwgcmF0ZXMgZm9yIGVhY2ggY2l0eS4gV2UgZm91bmQgdGhhdCBCb3N0b24gYW5kIFNhbiBGcmFuY2lzY28gaGF2ZSB0aGUgaGlnaGVzdCBwcm9wb3J0aW9uIG9mICJGYWlsIiBvdXRjb21lcy4gSW4gY29udHJhc3QsIE5ldyBZb3JrJ3MgcHJvZmlsZSBpcyBkb21pbmF0ZWQgYnkgIlBhc3MiIChyZWZsZWN0aW5nIHRoZWlyICdBJyBncmFkZXMpIGFuZCAiUGVuZGluZyIgcmVzdWx0cy4gVGhpcyBjb25maXJtcyB0aGF0IGVhY2ggY2l0eSdzIGdyYWRpbmcgc3lzdGVtIGlzIHVuaXF1ZSBhbmQgdGhhdCBvdXIgaW5zcGVjdGlvbl9vdXRjb21lIGNvbHVtbiBzdWNjZXNzZnVsbHkgY2FwdHVyZWQgdGhlc2UgZGlmZmVyZW5jZXMuCgpQbG90IDU6IFByb3BvcnRpb24gb2YgUmlzayBMZXZlbCBieSBDaXR5ClRoaXMgaXMgb25lIG9mIHRoZSBtb3N0IHN0cmlraW5nIGZpbmRpbmdzIHNvIGZhci4gQ2hpY2FnbyBhbmQgTmV3IFlvcmsgbG9nIGEgZHJhbWF0aWNhbGx5IGhpZ2hlciBwcm9wb3J0aW9uIG9mICJIaWdoIFJpc2siIHZpb2xhdGlvbnMgdGhhbiBCb3N0b24gYW5kIFNhbiBGcmFuY2lzY28uIEluIENoaWNhZ28sICJIaWdoIFJpc2siIGFwcGVhcnMgdG8gYmUgdGhlIG1vc3QgY29tbW9uIGNhdGVnb3J5LCB3aGlsZSBpbiBCb3N0b24sICJMb3cgUmlzayIgaXMgZG9taW5hbnQuIFRoaXMgbWF5IHJlZmxlY3QgZGlmZmVyZW50IHB1YmxpYyBoZWFsdGggZGVmaW5pdGlvbnMgb2YgInJpc2siIG9yIGRpZmZlcmVudCBhcmVhcyBvZiBmb2N1cyBmb3IgZWFjaCBjaXR5J3MgaW5zcGVjdG9ycy4KClBsb3QgNiAmIDc6IFNjb3JlIERpc3RyaWJ1dGlvbnMKVGhlc2UgdHdvIHBsb3RzICh3aGljaCB3ZSd2ZSBjb21iaW5lZCBmb3IgYW5hbHlzaXMpIGNvbmZpcm0gb3VyIGluc3BlY3Rpb25fb3V0Y29tZSBsb2dpYyBhbmQgcmV2ZWFsIHRoZSBpbnZlcnRlZCBuYXR1cmUgb2YgdGhlIHNjb3Jpbmcgc3lzdGVtcy4KCk5ZQyB1c2VzIGEgZGVtZXJpdCBzeXN0ZW06IEEgbG93ZXIgc2NvcmUgaXMgYmV0dGVyLiBPdXIgcGxvdCBzaG93cyB0aGF0ICJQYXNzIiAoR3JhZGUgQSkgaGFzIHRoZSBsb3dlc3Qgc2NvcmVzLCB3aGlsZSAiRmFpbCIgKEdyYWRlIEMpIGhhcyB0aGUgaGlnaGVzdC4KClNGIHVzZXMgYSBwb2ludHMtYmFzZWQgc3lzdGVtOiBBIGhpZ2hlciBzY29yZSBpcyBiZXR0ZXIuIE91ciBwbG90IGNvbmZpcm1zIHRoaXMsIHNob3dpbmcgIlBhc3MiICg5MCspIGhhcyB0aGUgaGlnaGVzdCBzY29yZXMgYW5kICJGYWlsIiAoNzEtODUpIGhhcyBsb3dlciBzY29yZXMuCgpUaGlzIGFuYWx5c2lzIHZhbGlkYXRlcyBvdXIgc3RhbmRhcmRpemF0aW9uIGFuZCBwcm92ZXMgdGhhdCB0aGUgdHdvIHNjb3Jpbmcgc3lzdGVtcyBhcmUgZGlyZWN0IG9wcG9zaXRlcy4KCiMjIyBFeHBsb3JpbmcgRmFpbCBSYXRlcyBPdmVyIFRpbWUgCmBgYHtyIEV4cGxvcmluZyBGYWlsIFJhdGVzfQoKIyBDcmVhdGUgYSBzdW1tYXJ5IHRhYmxlCmZhaWxzX2J5X3llYXIgPC0gaW5zcGVjdGlvbnMgfD4KICBmaWx0ZXIoaW5zcGVjdGlvbl9kYXRlID4gIjIwMDAtMDEtMDEiKSB8PiAjIGZpbHRlciBvdXQgJ2JhZCcgZGF0ZXMKICBtdXRhdGUoeWVhciA9IHllYXIoaW5zcGVjdGlvbl9kYXRlKSkgfD4KICBncm91cF9ieShjaXR5X3NvdXJjZSwgeWVhcikgfD4KICBzdW1tYXJpemUoCiAgICBmYWlsX3JhdGUgPSBtZWFuKGluc3BlY3Rpb25fb3V0Y29tZSA9PSAiRmFpbCIsIG5hLnJtID0gVFJVRSksCiAgICB0b3RhbF9pbnNwZWN0aW9ucyA9IG4oKQogICkgfD4KICBmaWx0ZXIodG90YWxfaW5zcGVjdGlvbnMgPiAxMDApICMgUmVtb3ZlIHllYXJzIHdpdGggdGlueSBkYXRhCgojIFBsb3QgdGhlIHN1bW1hcnkKZ2dwbG90KGZhaWxzX2J5X3llYXIsIGFlcyh4ID0geWVhciwgeSA9IGZhaWxfcmF0ZSwgY29sb3IgPSBjaXR5X3NvdXJjZSkpICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gbGFiZWxfcGVyY2VudCgpKSArICAgICAjIGZvcm1hdCB5LWF4aXMgYXMgcGVyY2VudGFnZQogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpICsgICAgICAgICAgICAgICAgICAgICAgICAgIyBhZGQgYmV0dGVyIGNvbG9ycwogIGxhYnMoCiAgICB0aXRsZSA9ICJGYWlsIFJhdGUgT3ZlciBUaW1lIGJ5IENpdHkiLCAKICAgIHkgPSAiUHJvcG9ydGlvbiBvZiBGYWlscyIsICAgICAgICAgICAgICAgICAgICAgICMgPC0tIEZpeCB5LWF4aXMgbGFiZWwKICAgIHggPSAiWWVhciIsCiAgICBjb2xvciA9ICJDaXR5IiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIDwtLSBGaXggbGVnZW5kIHRpdGxlCiAgKQoKIyBMZWFzdCBTdWNjZXNzZnVsIHppcGNvZGVzIGluIGVhY2ggY2l0eSBpbiB0aGUgZGF0YXNldApmYWlsc19ieV96aXAgPC0gaW5zcGVjdGlvbnMgfD4KICBmaWx0ZXIoaW5zcGVjdGlvbl9kYXRlID4gIjIwMDAtMDEtMDEiKSB8PiAjIEdvb2QgaWRlYSB0byBmaWx0ZXIgYmFkIGRhdGVzCiAgZ3JvdXBfYnkoY2l0eV9zb3VyY2UsIHppcF9jb2RlKSB8PgogIHN1bW1hcml6ZSgKICAgIGZhaWxfcmF0ZSA9IG1lYW4oaW5zcGVjdGlvbl9vdXRjb21lID09ICJGYWlsIiwgbmEucm0gPSBUUlVFKSwKICAgIHRvdGFsX2luc3BlY3Rpb25zID0gbigpCiAgKSB8PgogIGZpbHRlcih0b3RhbF9pbnNwZWN0aW9ucyA+IDEwMCkgfD4gIyBPbmx5IGluY2x1ZGUgemlwcyB3aXRoIDEwMCsgaW5zcGVjdGlvbnMKICB1bmdyb3VwKCkKCiMgU3VtbWFyeSB0YWJsZSBmb3IgemlwIGNvZGVzCmZhaWxzX2J5X3ppcCB8PgogIGdyb3VwX2J5KGNpdHlfc291cmNlKSB8PiAgICAgICMgR3JvdXAgYnkgY2l0eQogIHRvcF9uKDMsIGZhaWxfcmF0ZSkgfD4gICAgICAgICMgRmluZCB0aGUgdG9wIDMgKndpdGhpbiogdGhhdCBjaXR5CiAgdW5ncm91cCgpIHw+CiAgCiAgIyBUaGlzICdyZW9yZGVyX3dpdGhpbicgaXMgYSBzcGVjaWFsIHRyaWNrIHRvIG1ha2UgZmFjZXRzIHdvcmsKICBtdXRhdGUoCiAgICB6aXBfY29kZSA9IHRpZHl0ZXh0OjpyZW9yZGVyX3dpdGhpbih6aXBfY29kZSwgZmFpbF9yYXRlLCBjaXR5X3NvdXJjZSkKICApIHw+CgogIGdncGxvdChhZXMoeCA9IHppcF9jb2RlLCB5ID0gZmFpbF9yYXRlLCBmaWxsID0gY2l0eV9zb3VyY2UpKSArCiAgZ2VvbV9jb2woKSArCiAgdGlkeXRleHQ6OnNjYWxlX3hfcmVvcmRlcmVkKCkgKyAjIFRoaXMgbWFrZXMgdGhlIGxhYmVscyBwbG90IGNvcnJlY3RseQogIGZhY2V0X3dyYXAofiBjaXR5X3NvdXJjZSwgc2NhbGVzID0gImZyZWUiKSArICNDcmVhdGUgNCBzZXBhcmF0ZSBjaGFydHMKICBjb29yZF9mbGlwKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJUb3AgMyBaaXAgQ29kZXMgd2l0aCBIaWdoZXN0IEZhaWwgUmF0ZSBieSBDaXR5IiwKICAgIHggPSAiWmlwIENvZGUiLAogICAgeSA9ICJGYWlsIFJhdGUiCiAgKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKYGBgCgpGb2xsb3dpbmcgb3VyIGNpdHktbGV2ZWwgY29tcGFyaXNvbnMsIHdlIG1vdmVkIGludG8gb3VyIGZpcnN0IG11bHRpdmFyaWF0ZSBhbmFseXNpcyB0byBhbnN3ZXIgb3VyIHJlc2VhcmNoIHF1ZXN0aW9ucyBhYm91dCB3aGVyZSBhbmQgd2hlbiB2aW9sYXRpb25zIG9jY3VyLgoKUGxvdCA4OiBGYWlsIFJhdGUgT3ZlciBUaW1lIGJ5IENpdHkKVGhpcyBsaW5lIGdyYXBoIHBsb3RzIHRoZSBwcm9wb3J0aW9uIChwZXJjZW50YWdlKSBvZiAiRmFpbCIgb3V0Y29tZXMgZm9yIGVhY2ggY2l0eSwgZnJvbSAyMDA4IHRvIDIwMjUuIFRoaXMgaXMgb3VyIG1vc3Qgc2lnbmlmaWNhbnQgZmluZGluZyBzbyBmYXI6CgpEcmFtYXRpY2FsbHkgRGlmZmVyZW50IFN5c3RlbXM6IFRoZSBkZWZpbml0aW9uIG9mIGEgIkZhaWwiIGlzIGNsZWFybHkgbm90IHN0YW5kYXJkaXplZC4KCkJvc3RvbjogSGFzIGEgdmVyeSBoaWdoIGFuZCBjb25zaXN0ZW50ICJGYWlsIiByYXRlLCBob3ZlcmluZyBhcm91bmQgNjAlIGZvciB0aGUgZW50aXJlIDE1LXllYXIgcGVyaW9kLiBUaGlzIHN0cm9uZ2x5IHN1Z2dlc3RzIHRoYXQgQm9zdG9uJ3MgcmVzdWx0IGNvbHVtbiBsb2dzIGEgIkZhaWwiIGZvciBldmVuIG1pbm9yIGluZnJhY3Rpb25zLCBtYWtpbmcgaXQgYSB2ZXJ5IGNvbW1vbiBvdXRjb21lLgoKQ2hpY2FnbzogU2hvd3MgYSBwb3NpdGl2ZSB0cmVuZC4gSXRzIGZhaWwgcmF0ZSBoYXMgc3RlYWRpbHkgZGVjcmVhc2VkIGZyb20gfjI1JSBpbiAyMDEwIHRvIGEgc3RhYmxlIH4xOC0yMCUgaW4gcmVjZW50IHllYXJzLgoKTmV3IFlvcms6IEhhcyBhbiBleHRyZW1lbHkgbG93IGZhaWwgcmF0ZSwgY29uc2lzdGVudGx5IHN0YXlpbmcgYmVsb3cgMTAlLiBUaGlzIGFsaWducyBwZXJmZWN0bHkgd2l0aCB0aGVpciAiR3JhZGUgQSIgc3lzdGVtLCB3aGVyZSBhICdDJyAod2hpY2ggd2UgbWFwcGVkIHRvICJGYWlsIikgaXMgcmFyZS4KClNhbiBGcmFuY2lzY286IEFwcGVhcnMgdG8gaGF2ZSBhIGZhaWwgcmF0ZSBvZiBhcm91bmQgMzAlLCBsYW5kaW5nIGJldHdlZW4gQm9zdG9uIGFuZCB0aGUgb3RoZXIgdHdvIGNpdGllcy4KClBsb3QgOTogVG9wIDMgV29yc3QgWmlwIENvZGVzIGJ5IENpdHkKVGhpcyBiYXIgY2hhcnQgd2FzIGludGVuZGVkIHRvIGZpbmQgdGhlICJ3b3JzdCIgemlwIGNvZGVzIGFjcm9zcyB0aGUgZW50aXJlIGRhdGFzZXQuCldlIGhhdmUgbm93IHN1Y2Nlc3NmdWxseSBpZGVudGlmaWVkIHNwZWNpZmljIGdlb2dyYXBoaWMgYXJlYXMgb2YgY29uY2VybiBmb3IgZWFjaCBjaXR5OgoKQm9zdG9uOiAwMjExOS0zMjEyLCAwMjEyMAoKQ2hpY2FnbzogNjA4MjcsIDYwNjE5CgpOZXcgWW9yazogMTE0MzYsIDExNDI4CgpTYW4gRnJhbmNpc2NvOiA5NDEzNCwgOTQxMTgKCiMjIyBCb3N0b24gWmlwY29kZXMgTWFwCgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpib3NfaW5zcCA8LSBpbnNwZWN0aW9ucyB8PgogIGZpbHRlcihjaXR5X3NvdXJjZSA9PSAiQm9zdG9uIikKYm9zX3NocCA8LSBzdF9yZWFkKCJCb3N0b24gU2hhcGVmaWxlcy9aSVBfQ29kZXMuc2hwIikKCmJvc19ib3JkZXJzIDwtIGJvc19zaHAgfD4gc3RfdW5pb24oKSB8PgogIHN0X2J1ZmZlciguNSkKZ2dwbG90KGJvc19ib3JkZXJzKSArCiAgZ2VvbV9zZihkYXRhPWJvcywgYWVzKGZpbGwgPSBaSVA1KSkKCgojIERlbnNpdHkgbWFwIG9mIHJlc3RhdXJhbnRzIGluIGVhY2ggemlwY29kZQoKcnN0bnRfZGVuc2l0eSA8LSBib3NfaW5zcCB8PgogIGdyb3VwX2J5KHJlc3RhdXJhbnRfbmFtZSkgfD4KICBncm91cF9ieSh6aXBfY29kZSkgfD4KICBtdXRhdGUobl9wZXJfemlwID0gTigpKQoKYm9zJHppcF9jb2RlIDwtIGJvcyRaSVA1Cgpib3MgPC0gZnVsbF9qb2luKHJzdG50X2RlbnNpdHksIGJvcywgYnkgPSB6aXBfY29kZSkKCmdncGxvdChib3NfYm9yZGVycykgKwogIGdlb21fc2YoZGF0YT1ib3MsIGFlcyhmaWxsX25fcGVyX3ppcCkpCmBgYAoKVGhlcmUgYXJlIDQzIHppcCBjb2RlcyBpbiB0aGUgQ2l0eSBvZiBCb3N0b24KCiMjIyBUb3AgVmlvbGF0aW9ucyBPdmVyYWxsCgpgYGB7ciBUb3AgVmlvbGF0aW9ucyBPdmVyYWxsfQp0b3BfYmlncmFtcyA8LSBpbnNwZWN0aW9ucyB8PgogIHNhbXBsZV9mcmFjKDAuNSkgfD4gICMgVGFraW5nIGEgNTAlIHJhbmRvbSBzYW1wbGUgdG8gcmVkdWNlIG1lbW9yeSBsb2FkCiAgZmlsdGVyKCFpcy5uYSh2aW9sYXRpb25fZGVzYykpIHw+CiAgdW5uZXN0X3Rva2VucyhiaWdyYW0sIHZpb2xhdGlvbl9kZXNjLCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikgfD4KICBjb3VudChiaWdyYW0sIHNvcnQgPSBUUlVFKQoKIyBQbG90IHRoZSB0b3AgMjAKdG9wX2JpZ3JhbXMgfD4KICB0b3BfbigyMCkgfD4KICBnZ3Bsb3QoYWVzKHggPSByZW9yZGVyKGJpZ3JhbSwgbiksIHkgPSBuKSkgKwogIGdlb21fY29sKCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCAyMCBNb3N0IENvbW1vbiBWaW9sYXRpb24gUGhyYXNlcyAoNTAlIFNhbXBsZSkiLAogICAgeCA9ICJWaW9sYXRpb24gUGhyYXNlIChCaWdyYW0pIiwKICAgIHkgPSAiVG90YWwgQ291bnQiCiAgKQpgYGAKClRoaXMgcGxvdCwgZGVzcGl0ZSBzdWNjZXNzZnVsbHkgcHJvY2Vzc2luZyB0aGUgdGV4dCwgc2hvd3MgdGhhdCB0aGUgbW9zdCBjb21tb24gcGhyYXNlcyBhY3Jvc3MgYWxsIGNpdGllcyBhcmUgZ2VuZXJpYywgaGlnaC1mcmVxdWVuY3kgZnVuY3Rpb25hbCB3b3JkcyBsaWtlICdmb29kIGNvbnRhY3QnIGFuZCAnbm9uIGZvb2QnLiBXZSBkbyBub3Qgc2VlIHNwZWNpZmljIGlzc3VlcyBsaWtlICdyb2RlbnQnIG9yICdpbXByb3BlciB0ZW1wZXJhdHVyZScgaW4gdGhlIHRvcCAyMCwgY29uZmlybWluZyB0aGF0IHRoZXNlIGtleSBpc3N1ZXMgYXJlIGRpbHV0ZWQgYnkgY29tbW9uLCBnZW5lcmFsIHBocmFzZXMuIFRoaXMgdmFsaWRhdGVzIG91ciBuZXh0IHN0ZXAgdG8gdXNlIG1hbnVhbCBrZXl3b3JkIHNlYXJjaGluZyB0byBncm91cCB0aG91c2FuZHMgb2YgdW5pcXVlIHZpb2xhdGlvbnMgaW50byBtZWFuaW5nZnVsIGNhdGVnb3JpZXMuCgojIyMgRGF5cyBvZiB0aGUgd2VlayB0aGF0IHNlZSB0aGUgbW9zdCBpbnNwZWN0aW9ucwoKYGBge3IgSW5zcGVjdGlvbnMgYnkgRGF5IG9mIFdlZWt9Cmluc3BlY3Rpb25zIHw+IAogIG11dGF0ZSh3ZGF5ID0gd2RheShpbnNwZWN0aW9uX2RhdGUsIGxhYmVsID0gVFJVRSkpIHw+IAogIGNvdW50KHdkYXkpIHw+CiAgZ2dwbG90KGFlcyh3ZGF5LCBuKSkgKwogIGdlb21fY29sKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9jb21tYSgpKSArCiAgbGFicyh0aXRsZSA9ICJJbnNwZWN0aW9ucyBieSBEYXkgb2YgV2VlayIpCmBgYAoKVGhpcyBhbmFseXNpcyBjb25maXJtcyB0aGF0IGluc3BlY3Rpb24gZnJlcXVlbmN5IGlzIGhlYXZpbHkgc2tld2VkIHRvd2FyZCB3ZWVrZGF5cywgd2l0aCBhIHNsaWdodCBwZWFrIG9uIFR1ZXNkYXkuIFRoZSBsb3cgY291bnRzIG9uIFN1bmRheSBhbmQgU2F0dXJkYXkgIHN1Z2dlc3QgdGhhdCB3ZWVrZW5kIGluc3BlY3Rpb25zIGFyZSByYXJlIG9yIHJlc2VydmVkIG9ubHkgZm9yIHNwZWNpZmljIGZhY2lsaXRpZXMuCgojIyMgSW5zcGVjdGlvbiBGcmVxdWVuY3kgcGVyIFJlc3RhdXJhbnQKCmBgYHtyIEluc3BlY3Rpb25zIHBlciBSZXN0YXVyYW50fQpnZ3Bsb3QoaW5zcGVjdGlvbnMgfD4gY291bnQocmVzdGF1cmFudF9uYW1lKSwgYWVzKG4pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYnJlYWtzID0gc2VxKDAsIDUwLCBieSA9IDEpLCBjb2xvcj0iYmxhY2siLCBmaWxsPSJza3libHVlIikgKwogIGxhYnModGl0bGU9IkRpc3RyaWJ1dGlvbiBvZiBJbnNwZWN0aW9ucyBwZXIgUmVzdGF1cmFudCIsIHg9Ik51bWJlciBvZiBJbnNwZWN0aW9ucyIsIHk9Ik51bWJlciBvZiBSZXN0YXVyYW50cyIpCmBgYAoKVGhlIHRhbGxlc3QgYmFyIHNob3dzIHRoYXQgbmVhcmx5IDEwLDAwMCByZXN0YXVyYW50cyBoYXZlIGJlZW4gaW5zcGVjdGVkIG9ubHkgb25jZSAob3IgY2xvc2UgdG8gb25jZSkgZHVyaW5nIHRoZSBkYXRhc2V0J3MgdGltZSBmcmFtZS4gVGhlIG51bWJlciBvZiByZXN0YXVyYW50cyBkcm9wcyBvZmYgc3RlZXBseSBmb3IgYnVzaW5lc3NlcyBpbnNwZWN0ZWQganVzdCAyLCAzLCBvciA0IHRpbWVzLgpUaGUgbG9uZywgZmxhdCB0YWlsIG9uIHRoZSByaWdodCBpcyBoaWdobHkgc2lnbmlmaWNhbnQuIFdoaWxlIG1vc3QgYnVzaW5lc3NlcyBhcmUgaW5zcGVjdGVkIGluZnJlcXVlbnRseSwgYSBzbWFsbCBidXQgY29uc2lzdGVudCBudW1iZXIgb2YgcmVzdGF1cmFudHMgYXJlIGluc3BlY3RlZCAyMCwgMzAsIDQwLCBvciBldmVuIDUwKyB0aW1lcy4gVGhpcyBtYXkgYmUgZHVlIHRvIHJvdXRpbmUgaW5zcGVjdGlvbnMgaGFwcGVuaW5nLCBidXQgdGhpcyBpcyB1bmxpa2VseSBmb3IgdGhlIHRpbWUgcGVyaW9kIGNvdmVyZWQgaW4gb3VyIGRhdGEuIFRoaXMgY291ZGwgYWxzbyBzdWdnZXN0IHRoYXQgdGhlIGluc3BlY3Rpb24gc3lzdGVtIGlzIGVmZmVjdGl2ZWx5IHVzaW5nIGEgcmlzay1iYXNlZCBhcHByb2FjaC4gUmVzdGF1cmFudHMgdGhhdCBmYWlsIG9yIGhhdmUgc2VyaW91cyB2aW9sYXRpb25zIGFyZSBsaWtlbHkgcHVzaGVkIGludG8gcmUtaW5zcGVjdGlvbiBjeWNsZXMgb3IgcmVjZWl2ZSBtb3JlIGZyZXF1ZW50IHJvdXRpbmUgaW5zcGVjdGlvbnMuIENvbnZlcnNlbHksIHN1Y2Nlc3NmdWwgcmVzdGF1cmFudHMgYXJlIGluc3BlY3RlZCBsZXNzIG9mdGVuLCBmcmVlaW5nIHVwIHJlc291cmNlcy4KCiMjIEFuc3dlcmluZyBSZXNlYXJjaCBRdWVzdGlvbnMKCiMjIFNldW4ncyBBbmFseXNpcyAKIyMjIENhdGVnb3JpemUgVmlvbGF0aW9ucwpgYGB7ciBDYXRlZ29yaXplIFZpb2xhdGlvbnN9Cmluc3BlY3Rpb25zX2NhdGVnb3JpemVkIDwtIGluc3BlY3Rpb25zIHw+CiAgbXV0YXRlKAogICAgdmlvbGF0aW9uX2NhdGVnb3J5ID0gY2FzZV93aGVuKAogICAgICBzdHJfZGV0ZWN0KHZpb2xhdGlvbl9kZXNjLCAibWljZXxyb2RlbnR8ZHJvcHBpbmdzfGluc2VjdHN8cGVzdHN8aGFyYm9yYWdlIikgfiAiUGVzdCBDb250cm9sIiwKICAgICAgc3RyX2RldGVjdCh2aW9sYXRpb25fZGVzYywgInRlbXBlcmF0dXJlfGNvb2x8aG90LWhvbGRpbmd8Y29sZC1ob2xkaW5nfHJlZnJpZ2VyYXQiKSB+ICJGb29kIFRlbXBlcmF0dXJlIiwKICAgICAgc3RyX2RldGVjdCh2aW9sYXRpb25fZGVzYywgIndhc2h8c2FuaXRpenxjbGVhbnx3aXBpbmcgY2xvdGhzfGRpc2h3YXNoaW5nIikgfiAiU2FuaXRhdGlvbiAmIENsZWFuaW5nIiwKICAgICAgc3RyX2RldGVjdCh2aW9sYXRpb25fZGVzYywgImhhbmQgd2FzaHxoeWdpZW5lfG5vIGhhaXJ8YmFyZSBoYW5kIikgfiAiRW1wbG95ZWUgSHlnaWVuZSIsCiAgICAgIHN0cl9kZXRlY3QodmlvbGF0aW9uX2Rlc2MsICJjb250YW1pbmF0fGNyb3NzLWNvbnRhbWluYXRpb258cmF3fGNvdmVyZWR8cHJvdGVjdCIpIH4gIkNyb3NzLUNvbnRhbWluYXRpb24iLAogICAgICBzdHJfZGV0ZWN0KHZpb2xhdGlvbl9kZXNjLCAiZmxvb3J8d2FsbHxjZWlsaW5nfHBsdW1iaW5nfHZlbnRpbGF0aW9ufGdhcmJhZ2UiKSB+ICJGYWNpbGl0eS9NYWludGVuYW5jZSIsCiAgICAgIFRSVUUgfiAiT3RoZXIiCiAgICApCiAgKQoKI0NoZWNrIG5ldyBjYXRlZ29yaWVzCmluc3BlY3Rpb25zX2NhdGVnb3JpemVkIHw+CiAgY291bnQodmlvbGF0aW9uX2NhdGVnb3J5LCBzb3J0ID0gVFJVRSkKYGBgCgoKIyMjIENhdGVnb3JpemUgUmVzdGF1cmFudHMKYGBge3IgQ2F0ZWdvcml6ZSBSZXN0YXVyYW50c30KaW5zcGVjdGlvbnNfY2F0ZWdvcml6ZWQgPC0gaW5zcGVjdGlvbnNfY2F0ZWdvcml6ZWQgfD4KICBtdXRhdGUoCiAgICAjIENyZWF0ZSBvbmUgY29tYmluZWQgZGVzY3JpcHRpb24gY29sdW1uIHRvIHNlYXJjaAogICAgZGVzY19hbGwgPSBjb2FsZXNjZShjdWlzaW5lX2Rlc2NyaXB0aW9uLCBmYWNpbGl0eV90eXBlLCBkZXNjcmlwdCkgfD4gdG9sb3dlcigpLAogICAgCiAgICByZXN0YXVyYW50X2NhdGVnb3J5ID0gY2FzZV93aGVuKAogICAgICBzdHJfZGV0ZWN0KGRlc2NfYWxsLCAicGl6emF8cGl6emVyaWEiKSB+ICJQaXp6YSIsCiAgICAgIHN0cl9kZXRlY3QoZGVzY19hbGwsICJzdXNoaXxqYXBhbmVzZSIpIH4gIlN1c2hpL0phcGFuZXNlIiwKICAgICAgc3RyX2RldGVjdChkZXNjX2FsbCwgImNvZmZlZXxjYWZlfGJha2VyeXxkb251dCIpIH4gIkNvZmZlZS9CYWtlcnkiLAogICAgICBzdHJfZGV0ZWN0KGRlc2NfYWxsLCAibWV4aWNhbnx0YWNvIikgfiAiTWV4aWNhbiIsCiAgICAgIHN0cl9kZXRlY3QoZGVzY19hbGwsICJjaGluZXNlIikgfiAiQ2hpbmVzZSIsCiAgICAgIHN0cl9kZXRlY3QoZGVzY19hbGwsICJzYW5kd2ljaHxkZWxpfHN1YiIpIH4gIlNhbmR3aWNoL0RlbGkiLAogICAgICBzdHJfZGV0ZWN0KGRlc2NfYWxsLCAiYmFyfHRhdmVybnxwdWIiKSB+ICJCYXIvUHViIiwKICAgICAgc3RyX2RldGVjdChkZXNjX2FsbCwgInJlc3RhdXJhbnR8YW1lcmljYW4iKSB+ICJSZXN0YXVyYW50IChHZW5lcmFsKSIsCiAgICAgIHN0cl9kZXRlY3QoZGVzY19hbGwsICJzY2hvb2x8Z3JvY2VyeXxtYXJrZXR8Y2F0ZXJlcnxraXRjaGVuIikgfiAiT3RoZXIgKEdyb2NlcnkvU2Nob29sL0V0Yy4pIiwKICAgICAgVFJVRSB+ICJPdGhlciIKICAgICkKICApCgojQ2hlY2sgbmV3IGNhdGVnb3JpZXMKaW5zcGVjdGlvbnNfY2F0ZWdvcml6ZWQgfD4KICBjb3VudChyZXN0YXVyYW50X2NhdGVnb3J5LCBzb3J0ID0gVFJVRSkKYGBgCgojIyMgVmlvbGF0aW9uICJGaW5nZXJwcmludCIgUGxvdApgYGB7ciBWaW9sYXRpb24gIkZpbmdlcnByaW50IiBQbG90fQojU3VtbWFyeSB0YWJsZQp2aW9sYXRpb25fZmluZ2VycHJpbnQgPC0gaW5zcGVjdGlvbnNfY2F0ZWdvcml6ZWQgfD4KICBmaWx0ZXIoCiAgICByZXN0YXVyYW50X2NhdGVnb3J5ICE9ICJPdGhlciIsCiAgICByZXN0YXVyYW50X2NhdGVnb3J5ICE9ICJPdGhlciAoR3JvY2VyeS9TY2hvb2wvRXRjLikiLAogICAgdmlvbGF0aW9uX2NhdGVnb3J5ICE9ICJPdGhlciIKICApIHw+CiAgY291bnQocmVzdGF1cmFudF9jYXRlZ29yeSwgdmlvbGF0aW9uX2NhdGVnb3J5KSB8PgogIGdyb3VwX2J5KHJlc3RhdXJhbnRfY2F0ZWdvcnkpIHw+CiAgbXV0YXRlKHByb3BvcnRpb24gPSBuIC8gc3VtKG4pKSB8PgogIHVuZ3JvdXAoKQoKIyBQbG90IHRoZSAiZmluZ2VycHJpbnQiCmdncGxvdCh2aW9sYXRpb25fZmluZ2VycHJpbnQsIAogICAgICAgYWVzKHggPSB2aW9sYXRpb25fY2F0ZWdvcnksIHkgPSBwcm9wb3J0aW9uLCBmaWxsID0gdmlvbGF0aW9uX2NhdGVnb3J5KSkgKwogIGdlb21fY29sKCkgKwogIGZhY2V0X3dyYXAofiByZXN0YXVyYW50X2NhdGVnb3J5KSArIAogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBsYWJlbF9wZXJjZW50KCkpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICApICsKICBsYWJzKAogICAgdGl0bGUgPSAiVmlvbGF0aW9uICdGaW5nZXJwcmludCcgYnkgUmVzdGF1cmFudCBDYXRlZ29yeSIsCiAgICB5ID0gIlByb3BvcnRpb24gb2YgQWxsIFZpb2xhdGlvbnMiLAogICAgeCA9ICJWaW9sYXRpb24gVHlwZSIsCiAgICBmaWxsID0gIlZpb2xhdGlvbiBDYXRlZ29yeSIKICApCmBgYAoKUmVzdGF1cmFudCBjYXRlZ29yaWVzIGRvIGRpc3Byb3BvcnRpb25hdGVseSByZWNlaXZlIGNlcnRhaW4gdmlvbGF0aW9uIHR5cGVzLiBXaGlsZSAiU2FuaXRhdGlvbiAmIENsZWFuaW5nIiBpcyBhIHVuaXZlcnNhbCBwcm9ibGVtLCBzcGVjaWZpYyBtb2RlbHMgY2FycnkgdW5pcXVlIHJpc2tzLiAKVGhlIG1vc3QgaW1wb3J0YW50IHRha2Vhd2F5IGlzIHRoYXQgU2FuaXRhdGlvbiAmIENsZWFuaW5nIChwaW5rKSBhbmQgUGVzdCBDb250cm9sIChibHVlKSBhcmUgdGhlIHR3byBsYXJnZXN0IHZpb2xhdGlvbiBjYXRlZ29yaWVzIGFjcm9zcyBuZWFybHkgYWxsIHJlc3RhdXJhbnQgdHlwZXMuIEhvd2V2ZXIsIHRoZSBwcm9wb3J0aW9uIG9mIG90aGVyIGtleSBjYXRlZ29yaWVzIHJldmVhbHMgaW1wb3J0YW50IGRpZmZlcmVuY2VzOgoKUGVzdCBDb250cm9sIERvbWluYW5jZToKClN1c2hpL0phcGFuZXNlLCBTYW5kd2ljaC9EZWxpLCBhbmQgQmFyL1B1YnMgaGF2ZSB0aGUgaGlnaGVzdCBwcm9wb3J0aW9uIG9mIFBlc3QgQ29udHJvbCB2aW9sYXRpb25zLCBjb25zaXN0ZW50bHkgbWFraW5nIHVwIG92ZXIgMjUlIG9mIHRoZWlyIHRvdGFsIGlzc3Vlcy4KClNhbml0YXRpb24gJiBDbGVhbmluZyBGb2N1czoKCkNvZmZlZS9CYWtlcnksIFBpenphLCBhbmQgQ2hpbmVzZSByZXN0YXVyYW50cyBhcmUgaGlnaGx5IGRvbWluYXRlZCBieSBTYW5pdGF0aW9uICYgQ2xlYW5pbmcgdmlvbGF0aW9ucyAocGluayksIHdpdGggdGhpcyBjYXRlZ29yeSBvZnRlbiBleGNlZWRpbmcgNDAlIG9mIHRoZWlyIHRvdGFsIHZpb2xhdGlvbnMuCgpGb29kIFRlbXBlcmF0dXJlIFJpc2sgKFRoZSBPdXRsaWVyKToKClJlc3RhdXJhbnQgKEdlbmVyYWwpIGlzIHRoZSBvbmx5IGNhdGVnb3J5IHdoZXJlIEZvb2QgVGVtcGVyYXR1cmUgKHRlYWwpIG1ha2VzIHVwIHRoZSBsYXJnZXN0IG5vbi1TYW5pdGF0aW9uL1Blc3Qgc2hhcmUsIGhpdHRpbmcgYXBwcm94aW1hdGVseSAyNeKAkzMwJSBvZiBpdHMgdmlvbGF0aW9ucy4gVGhpcyBzdWdnZXN0cyB0aGF0IGJ1c2luZXNzZXMgd2l0aCBkaXZlcnNlIG1lbnVzIGFuZCBjb21wbGV4IGNvb2tpbmcgcHJvY2Vzc2VzIGFyZSB1bmlxdWVseSBwcm9uZSB0byB0ZW1wZXJhdHVyZS1yZWxhdGVkIGZhaWx1cmVzLgoKQ3Jvc3MtQ29udGFtaW5hdGlvbiBSaXNrOgoKTWV4aWNhbiBhbmQgU2FuZHdpY2gvRGVsaSByZXN0YXVyYW50cyBzaG93IGEgc2xpZ2h0bHkgZWxldmF0ZWQgcHJvcG9ydGlvbmFsIHJpc2sgZm9yIENyb3NzLUNvbnRhbWluYXRpb24gKHJlZCksIG9mdGVuIHJlbGF0ZWQgdG8gdGhlIGhpZ2ggdm9sdW1lIG9mIHJhdyBwcmVwYXJhdGlvbiAoZS5nLiwgY3V0dGluZyB2ZWdldGFibGVzLCBwcmVwYXJpbmcgc2Fsc2FzLCBoYW5kbGluZyBkZWxpIG1lYXRzKS4KCiMjIyBTdGFuZGFyZGl6ZSBJbnNwZWN0aW9uIFR5cGVzCmBgYHtyIFN0YW5kYXJkaXplIEluc3BlY3Rpb24gVHlwZXN9Cmluc3BlY3Rpb25zX2NhdGVnb3JpemVkIDwtIGluc3BlY3Rpb25zX2NhdGVnb3JpemVkIHw+CiAgbXV0YXRlKAogICAgdHlwZV9sb3dlciA9IHRvbG93ZXIoaW5zcGVjdGlvbl90eXBlKSwKICAgIAogICAgaW5zcGVjdGlvbl90eXBlX3N0YW5kYXJkID0gY2FzZV93aGVuKAogICAgICAjIEtleXdvcmRzIGZvciBjb21wbGFpbnQKICAgICAgc3RyX2RldGVjdCh0eXBlX2xvd2VyLCAiY29tcGxhaW50fDMxMXxvd25lciBjb21wbGFpbnQiKSB+ICJDb21wbGFpbnQiLAogICAgICAKICAgICAgIyBLZXl3b3JkcyBmb3Igcm91dGluZQogICAgICBzdHJfZGV0ZWN0KHR5cGVfbG93ZXIsICJyb3V0aW5lfGN5Y2xlfGNhbnZhc3N8cmVndWxhciIpIH4gIlJvdXRpbmUiLAogICAgICAKICAgICAgIyBLZXl3b3JkcyBmb3IgZm9sbG93LXVwcwogICAgICBzdHJfZGV0ZWN0KHR5cGVfbG93ZXIsICJyZS1pbnNwZWN0aW9ufHJlaW5zcGVjdGlvbnxmb2xsb3ctdXAiKSB+ICJGb2xsb3ctVXAiLAogICAgICAKICAgICAgVFJVRSB+ICJPdGhlciIKICAgICkKICApCgojbmV3IHN0YW5kYXJkaXplZCBjYXRlZ29yaWVzCmluc3BlY3Rpb25zX2NhdGVnb3JpemVkIHw+CiAgY291bnQoaW5zcGVjdGlvbl90eXBlX3N0YW5kYXJkLCBzb3J0ID0gVFJVRSkKYGBgCgojIyMgUGxvdCBTZXZlcml0eSBieSBJbnNwZWN0aW9uIFR5cGUKYGBge3IgUGxvdCBTZXZlcml0eSBieSBJbnNwZWN0aW9uIFR5cGV9CgppbnNwZWN0aW9uc19jYXRlZ29yaXplZCB8PgogICMgMS4gRmlsdGVyIHRoZSBkYXRhIChObyBjaGFuZ2VzIG5lZWRlZCBoZXJlKQogIGZpbHRlcigKICAgIGluc3BlY3Rpb25fdHlwZV9zdGFuZGFyZCAlaW4lIGMoIlJvdXRpbmUiLCAiQ29tcGxhaW50IiksCiAgICByaXNrX2xldmVsX3N0YW5kYXJkICE9ICJVbmtub3duIgogICkgfD4gIyA8LS0tIFBJUEUgVE8gVEhFIE5FWFQgU1RFUAogIAogICMgMi4gTXV0YXRlIChDb252ZXJ0IHRvIEZhY3RvcikKICBtdXRhdGUoCiAgICByaXNrX2xldmVsX3N0YW5kYXJkID0gZmFjdG9yKAogICAgICByaXNrX2xldmVsX3N0YW5kYXJkLCAKICAgICAgIyBTZXQgdGhlIGRlc2lyZWQgaGllcmFyY2hpY2FsIG9yZGVyCiAgICAgIGxldmVscyA9IGMoIkhpZ2giLCAiTWVkaXVtIiwgIkxvdyIpLAogICAgICBvcmRlcmVkID0gVFJVRQogICAgKQogICkgfD4gIyA8LS0tIENPUlJFQ1QgUElQRSBQTEFDRU1FTlQgKE91dHNpZGUgdGhlIGZpbmFsIG11dGF0ZSBwYXJlbnRoZXNpcykKICAKICAjIDMuIFBsb3QgcHJvcG9ydGlvbnMKICBnZ3Bsb3QoYWVzKHggPSBpbnNwZWN0aW9uX3R5cGVfc3RhbmRhcmQsIGZpbGwgPSByaXNrX2xldmVsX3N0YW5kYXJkKSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImZpbGwiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6bGFiZWxfcGVyY2VudCgpKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Qob3B0aW9uID0gIkMiKSArCiAgbGFicygKICAgIHRpdGxlID0gIlZpb2xhdGlvbiBTZXZlcml0eSBieSBJbnNwZWN0aW9uIFR5cGUiLAogICAgeCA9ICJJbnNwZWN0aW9uIFR5cGUiLAogICAgeSA9ICJQcm9wb3J0aW9uIG9mIFZpb2xhdGlvbnMiLAogICAgZmlsbCA9ICJSaXNrIExldmVsIgogICkKYGBgCgpUaGUgcHJvcG9ydGlvbmFsIHBsb3QgY2xlYXJseSBzaG93cyB0aGF0IENvbXBsYWludC1Ecml2ZW4gaW5zcGVjdGlvbnMgYXJlIG1vcmUgbGlrZWx5IHRvIGZpbmQgc2V2ZXJlIHByb2JsZW1zIHRoYW4gUm91dGluZSBpbnNwZWN0aW9uczEyLiBUaGUgcHJvcG9ydGlvbiBvZiBIaWdoIFJpc2sgdmlvbGF0aW9ucyBpcyB2aXN1YWxseSBsYXJnZXIgaW4gdGhlIENvbXBsYWludCBjb2x1bW4gdGhhbiBpbiB0aGUgUm91dGluZSBjb2x1bW4xMy4gVGhpcyBzdWdnZXN0cyB0aGUgcHVibGljIGlzIGVmZmVjdGl2ZSBhdCByZXBvcnRpbmcgcmVzdGF1cmFudHMgdGhhdCBwb3NlIGFuIGltbWVkaWF0ZSBwdWJsaWMgaGVhbHRoIHJpc2suCgojIyBQbG90IFZpb2xhdGlvbiBUeXBlIGJ5IEluc3BlY3Rpb24gVHlwZQpgYGB7ciBQbG90IFZpb2xhdGlvbiBUeXBlIGJ5IEluc3BlY3Rpb24gVHlwZX0KaW5zcGVjdGlvbnNfY2F0ZWdvcml6ZWQgfD4KICBmaWx0ZXIoCiAgICBpbnNwZWN0aW9uX3R5cGVfc3RhbmRhcmQgJWluJSBjKCJSb3V0aW5lIiwgIkNvbXBsYWludCIpLAogICAgdmlvbGF0aW9uX2NhdGVnb3J5ICE9ICJPdGhlciIgIyBSZW1vdmUgJ090aGVyJyB2aW9sYXRpb25zCiAgKSB8PgogIAogICMgUGxvdCBwcm9wb3J0aW9ucwogIGdncGxvdChhZXMoeCA9IGluc3BlY3Rpb25fdHlwZV9zdGFuZGFyZCwgZmlsbCA9IHZpb2xhdGlvbl9jYXRlZ29yeSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX3BlcmNlbnQoKSkgKwogIHNjYWxlX2ZpbGxfdmlyaWRpc19kKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWaW9sYXRpb24gVHlwZXMgYnkgSW5zcGVjdGlvbiBUeXBlIiwKICAgIHggPSAiSW5zcGVjdGlvbiBUeXBlIiwKICAgIHkgPSAiUHJvcG9ydGlvbiBvZiBWaW9sYXRpb25zIiwKICAgIGZpbGwgPSAiVmlvbGF0aW9uIENhdGVnb3J5IgogICkgKwogIGNvb3JkX2ZsaXAoKSAjIEZsaXAgYXhlcyB0byBtYWtlIGNhdGVnb3JpZXMgZWFzaWVyIHRvIHJlYWQKYGBgCgpXaGVuIGxvb2tpbmcgYXQgdmlvbGF0aW9uIHR5cGUsIENvbXBsYWludCBpbnNwZWN0aW9ucyBhcmUgZGlzcHJvcG9ydGlvbmF0ZWx5IGZvY3VzZWQgb24gUGVzdCBDb250cm9sIGFuZCBGb29kIFRlbXBlcmF0dXJlIGlzc3Vlcy4gSW4gY29udHJhc3QsIFJvdXRpbmUgaW5zcGVjdGlvbnMgZmluZCBhIG11Y2ggaGlnaGVyIHByb3BvcnRpb24gb2YgU2FuaXRhdGlvbiAmIENsZWFuaW5nIGFuZCBGYWNpbGl0eS9NYWludGVuYW5jZSBwcm9ibGVtcy4gVGhpcyBzdWdnZXN0cyB0aGF0IHBhdHJvbnMgYXJlIHF1aWNrIHRvIHJlcG9ydCB2aXNpYmxlIHNpZ25zIG9mIHBlc3RzIG9yIHRlbXBlcmF0dXJlIGlzc3Vlcywgd2hpbGUgaW5zcGVjdG9ycyBmaW5kIG1vcmUgc3RydWN0dXJhbC9oeWdpZW5lIHByb2JsZW1zIGR1cmluZyB1bmFubm91bmNlZCwgY29tcHJlaGVuc2l2ZSBjaGVja3MuCgpPdXIgYW5hbHlzaXMgY29uZmlybXMgdHdvIGNyaXRpY2FsIHJlbGF0aW9uc2hpcHM6CgoxLiAgKipCdXNpbmVzcyBNb2RlbCBSaXNrOioqIFRoZSB0eXBlIG9mIGN1aXNpbmUgYSByZXN0YXVyYW50IHNlcnZlcyBjcmVhdGVzIGEgdW5pcXVlICJmaW5nZXJwcmludCIgb2YgaGVhbHRoIHJpc2tzIChRMSkuIENvbXBsZXggY29va2luZyAoUmVzdGF1cmFudCBHZW5lcmFsKSBjb3JyZWxhdGVzIHdpdGggKipGb29kIFRlbXBlcmF0dXJlKiogaXNzdWVzLCB3aGlsZSBoaWdoLXZvbHVtZSByYXcgcHJlcGFyYXRpb24gKFN1c2hpL0RlbGkpIGNvcnJlbGF0ZXMgd2l0aCAqKlBlc3QgQ29udHJvbCoqIGFuZCAqKkNyb3NzLUNvbnRhbWluYXRpb24qKi4KMi4gICoqSW5zcGVjdGlvbiBUeXBlIEJpYXM6KiogUHVibGljIGNvbXBsYWludHMgKFEyKSBhcmUgaGlnaGx5IGVmZmVjdGl2ZSBhdCBmbGFnZ2luZyBpbW1lZGlhdGUgcHVibGljIGhlYWx0aCB0aHJlYXRzLCBkZW1vbnN0cmF0aW5nIGEgaGlnaGVyIHByb3BvcnRpb25hbCBpbmNpZGVuY2Ugb2YgKipIaWdoIFJpc2sqKiB2aW9sYXRpb25zIGFuZCAqKlBlc3QgQ29udHJvbCoqIHByb2JsZW1zIGNvbXBhcmVkIHRvIHJvdXRpbmUgaW5zcGVjdGlvbnMu